package cashpointer.core.dao;

import cashpointer.core.model.Cashpoint;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Klasa wspomagajaca operacje bazodanowe na tabeli Cashpointer.
 * @author Wojciech Topolski
 * @version 2009-03-17
 */
public class CashpointDaoHibernate extends HibernateDaoSupport implements CashpointDao {

    // Logger.
    static private Log log = LogFactory.getLog(CashpointDaoHibernate.class);

    /**
     * Funkcja dodaje nowego badz aktualizuje juz istniejacy bankomat.
     * @param cashpoint Cashpoint
     */
    public void save(Cashpoint cashpoint) {
        getHibernateTemplate().saveOrUpdate(cashpoint);
    }

    /**
     * Funkcja usuwa bankomat.
     * @param cashpoint Cashpoint
     */
    public void delete(Cashpoint cashpoint) {
        getHibernateTemplate().delete(cashpoint);
    }

    /**
     * Funkcja pobiera bankomat za pomoca jego id.
     * @param id Long
     */
    public Cashpoint getById(Long id) {
        return (Cashpoint) getHibernateTemplate().get(Cashpoint.class, id);
    }

    /**
     * Funkcja pobiera bankomat za pomoca jego hashCode.
     * @param id int
     */
    public Cashpoint getByHashCode(int hashCode) {
        List<Cashpoint> cashpoints = getHibernateTemplate().findByNamedQueryAndNamedParam("cashpoint.get.by.hashcode", "hashcode", hashCode);

        if (cashpoints != null && cashpoints.size() == 1) {
            return cashpoints.get(0);
        }

        return null;
    }

    /**
     * Funkcja pobiera liste bankomatow gdzie wersja START jest rowna z podana.
     * Wersja STOP musi byc null.
     * @param start String
     * @return List<Owner>
     */
    public List<Cashpoint> getByStart(String start) {
        List<Cashpoint> cashpoints = getHibernateTemplate().findByNamedQueryAndNamedParam("cashpoints.get.by.start", "start", start);
        return cashpoints;
    }

    /**
     * Funkcja pobiera liste bankomatow gdzie wersja STOP jest rowna z podana.
     * Wersja START musi byc wypelniona
     * @param  stop String
     * @return List<Owner>
     */
    public List<Cashpoint> getByStop(String stop) {
        List<Cashpoint> cashpoints = getHibernateTemplate().findByNamedQueryAndNamedParam("cashpoints.get.by.stop", "stop", stop);
        return cashpoints;
    }

    /**
     * Funkcja pobiera liste bankomatow gdzie wersja STOP jest null.
     * Wersja START musi byc wypelniona. Czyli wszystkie aktywne.
     * @return List<Cashpoint>
     */
    public List<Cashpoint> getAllActive() {
        List<Cashpoint> cashpoints = getHibernateTemplate().findByNamedQuery("cashpoints.get.all.active");
        return cashpoints;
    }

    /**
     * Funkcja pobiera liste wszystkie bankomaty.
     * @return List<Owner>
     */
    public List<Cashpoint> getAll() {
        return getHibernateTemplate().loadAll(Cashpoint.class);
    }

    /**
     * Funkcja zapisuje lite bankomatow do bazy danych.
     * @param owners List<Owner>
     */
    public void saveAll(List<Cashpoint> cashpoints) {
        getHibernateTemplate().saveOrUpdateAll(cashpoints);
    }

    /**
     * Funkcja pobiera mape z identyfikatorami i hashcodami bankomatow.
     * @return List<Owner>
     */
    public Map<Integer, Integer> getAllHashCodes() {
        Map<Integer, Integer> hashcodes = new HashMap<Integer, Integer>();

        Session session = this.getSession();
        if (session != null) {
            Criteria criteria = session.createCriteria(Cashpoint.class);
            criteria.setProjection(Projections.property("hashcode"));
            criteria.addOrder(Order.asc("hashcode"));
            List<Integer> list = criteria.list();

            for (Integer value : list) {
                hashcodes.put(value, 0);
            }
        }

        return hashcodes;
    }

    /**
     * Funkcja wykonuje rollback podanej wersji.
     */
    public void rollback(String version) {
        Session session = this.getSession();
        if (session != null) {
            // Wycofuje nowe bankomaty z bazy
            try {
                Query query = session.createQuery("delete from Cashpoint c where c.start = :version");
                if (query != null) {
                    query.setString("version", version);
                    query.executeUpdate();
                }

                // Wycofuje deaktywacje bankomatow
                try {
                    query = session.createQuery("update Cashpoint c set c.stop=null where c.stop = :version");
                    if (query != null) {
                        query.setString("version", version);
                        query.executeUpdate();
                    }
                }
                catch (HibernateException he) {
                    if (log.isErrorEnabled()) {
                        log.error("[CashpointDaoHibernate::rolback(...)] Blad podczas wycofania deaktywacji bankomatow!!!", he);
                    }
                }
            }
            catch (HibernateException he) {
                if (log.isErrorEnabled()) {
                    log.error("[CashpointDaoHibernate::rolback(...)] Blad podczas wycofywania nowych bankomatow!!!", he);
                }
            }
        }
        else {
            if (log.isErrorEnabled()) {
                log.error("[CashpointDaoHibernate::rolback(...)] Brak sesji.");
            }
        }
    }
}
